package com.heima.admin.aop;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.admin.mapper.AdUserEquipmentMapper;
import com.heima.admin.mapper.AdUserLoginMapper;
import com.heima.admin.mapper.OperateLogMapper;
import com.heima.model.admin.pojos.AdOperateLog;
import com.heima.model.admin.pojos.AdUser;
import com.heima.model.admin.pojos.AdUserEquipment;
import com.heima.model.admin.pojos.AdUserLogin;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.utils.common.IpUtil;
import com.heima.utils.common.WmThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import nl.bitwalker.useragentutils.OperatingSystem;
import nl.bitwalker.useragentutils.UserAgent;
import org.apache.http.HttpStatus;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Aspect
@Component
public class LogAspect {


    @Autowired
    private OperateLogMapper operateLogMapper;

    @Autowired
    private AdUserLoginMapper adUserLoginMapper;
    @Autowired
    private AdUserEquipmentMapper adUserEquipmentMapper;

    private final static Integer ZORE = 0;
    private final static Integer ONE = 1;
    private final static Integer TWO = 2;
    private final static Integer THREE = 3;
    private final static Integer FOUR = 4;
    private final static Integer NINE = 4;
    private final static String CLAZZ = "类:";
    private final static String SPILT = ",";
    private final static String SPILICT = ".";
    private final static String METHED = "方法名:";
    private final static String PHONETYPEONE = "ANDROID";
    private final static String PHONETYPETOW = "IOS";
    private final static String PHONETYPETHREE = "PAD";
    private final static String HEADERONE = "User-Agent";
    private final static String HEADERUSER = "user";
    private final static String CLAZZA = "com.heima.admin.controller.LoginController";
    private final static String CLAZZB = "com.heima.admin.controller.ApAuthController";
    private final static String CLAZZC = "com.heima.admin.controller.AdChannelController";
    private final static String CLAZZD = "com.heima.admin.controller.AdSensitiveController";

    @Pointcut("execution(* com.heima.admin.controller.*.*(..))")
    public void pt() {
    }

    @Around("pt()")
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
        log.info("进入切面");
        log.info("+++++++++++++++++++++++++++++++++++++++++++++++++");
        //
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //获得类名
        String className = pjp.getTarget().getClass().getName();
        //获得方法名
        String methodName = pjp.getSignature().getName();
        //放行
        Object result = pjp.proceed();
        //
        AdOperateLog log = new AdOperateLog();
        //登录ip地址
        String ip = IpUtil.getIpAddr(request).split(SPILT)[ZORE];
        log.setIp(ip);
        //获得操作人id
        if (!CLAZZA.equals(className)) {
            //
            Integer userId = WmThreadLocalUtil.getUser().getApUserId();
            log.setUserId(userId);
        } else {
            try {
                String returnValue = JSON.toJSONString(result);
                ResponseResult responseResult = JSON.parseObject(returnValue, ResponseResult.class);
                if (responseResult.getCode() == HttpStatus.SC_OK) {
                    insert(request, log, ip, responseResult);
                } else {
                    return result;
                }
            } catch (Exception e) {
                return result;
            }
        }
        insertOpLog(className, methodName, log);

        return result;
    }

    /**
     * 新增操作表
     * @param className
     * @param methodName
     * @param adOperateLog
     */
    public void insertOpLog(String className, String methodName, AdOperateLog adOperateLog) {
        log.info("新增后台操作行为日志");
        log.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        log.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        log.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        log.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        log.info("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        //设置参数
        //获得操作时间
        adOperateLog.setCreatedTime(LocalDateTime.now());

        operate(adOperateLog, className, methodName);

        //封装
        LambdaQueryWrapper<AdUserEquipment> wrapper = Wrappers.<AdUserEquipment>lambdaQuery()
                .eq(AdUserEquipment::getUserId, adOperateLog.getUserId())
                .orderByDesc(AdUserEquipment::getCreatedTime);
        List<AdUserEquipment> adUserEquipments = adUserEquipmentMapper.selectList(wrapper);
        AdUserEquipment adUserEquipment = adUserEquipments.get(ZORE);
        if (!StringUtils.isEmpty(adUserEquipment)){
            adOperateLog.setEquipmentId(Long.parseLong(adUserEquipment.getId().toString()));
        }
        //
        operateLogMapper.insert(adOperateLog);
    }

    /**
     * 登录双表新增操作
     * @param request
     * @param log
     * @param ip
     * @param responseResult
     */
    private void insert(HttpServletRequest request, AdOperateLog log, String ip, ResponseResult responseResult) {
        AdUserEquipment adUserEquipment = new AdUserEquipment();
        //
        JSONObject data = (JSONObject) responseResult.getData();
        Object user = data.get(HEADERUSER);
        String json = JSON.toJSONString(user);
        AdUser adUser = JSON.parseObject(json, AdUser.class);
        //
        if (!StringUtils.isEmpty(adUser)){
            log.setUserId(adUser.getId());
            //
            adUserEquipment.setUserId(adUser.getId());
            adUserEquipment.setCreatedTime(LocalDateTime.now());
            equipment(request,adUserEquipment);
            //
            adUserEquipmentMapper.insert(adUserEquipment);
            //
            insertLoginLog(ip, adUserEquipment, adUser);
        }
    }

    /**
     * 员工登录日志
     * @param ip
     * @param adUserEquipment
     * @param adUser
     */
    public void insertLoginLog(String ip, AdUserEquipment adUserEquipment, AdUser adUser) {
        log.info("登录日志");
        log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        log.info("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        AdUserLogin adUserLogin = new AdUserLogin();
        adUserLogin.setUserId(adUser.getId());
        adUserLogin.setIp(ip);
        adUserLogin.setCreatedTime(adUserEquipment.getCreatedTime());
        adUserLogin.setEquipmentId(adUserEquipment.getId());
        adUserLoginMapper.insert(adUserLogin);
    }

    /**
     * 登陆设备表
     * @param request
     * @param adUserEquipment
     */
    private static void equipment(HttpServletRequest request,AdUserEquipment adUserEquipment) {
        //获取浏览器信息
        String ua = request.getHeader(HEADERONE);
        //转成UserAgent对象
        UserAgent userAgent = UserAgent.parseUserAgentString(ua);
        //获取系统信息
        OperatingSystem operatingSystem = userAgent.getOperatingSystem();
        String name = operatingSystem.getGroup().getName();
        //系统名称
        String system = operatingSystem.getName();
        //
        adUserEquipment.setSys(system);
        adUserEquipment.setVersion(name);
        if (PHONETYPEONE.equals(name)){
            adUserEquipment.setType(ONE);
        }else if (PHONETYPETOW.equals(name)){
            adUserEquipment.setType(TWO);
        }else if (PHONETYPETHREE.equals(name)){
            adUserEquipment.setType(THREE);
        }else {
            adUserEquipment.setType(NINE);
        }

    }

    /**
     * 新增操作表的类型
     * @param log
     * @param className
     * @param methodName
     */
    private static void operate(AdOperateLog log, String className, String methodName) {
        if (CLAZZA.equals(className)) {
            log.setType(ZORE);
            setDes(log, className, methodName);
        } else if (CLAZZB.equals(className)) {
            log.setType(ONE);
            setDes(log, className, methodName);
        } else if (CLAZZC.equals(className)) {
            log.setType(TWO);
            setDes(log, className, methodName);
        } else if (CLAZZD.equals(className)) {
            log.setType(FOUR);
            setDes(log, className, methodName);
        } else {
            log.setType(THREE);
            setDes(log, className, methodName);
        }
    }

    /**
     * 新增操作表的描述
     * @param log
     * @param className
     * @param methodName
     */
    private static void setDes(AdOperateLog log, String className, String methodName) {
        log.setDescription(CLAZZ + className.substring(className.lastIndexOf(SPILICT) + ONE)
                + SPILT + METHED + methodName);

    }
}
